import cv2
from loguru import logger
from vision_utils import *

from decision_util import (
    GameStatus,
    DecisionUtil,
    check_winner,
    get_board_from_pieces,
)
from vision_utils import loopok
import time

# {
#     "center": (249, 239), 棋子圆心位置
#     "axes": 15, 棋子半径
#     "type": 1, 棋子颜色 1白X 0黑O
#     "rect": (
#         (217.00003051757812, 212.55001831054688),
#         (70.7073974609375, 70.7073974609375),
#         1.945142149925232,
#     ),
#     "grid": (2, 1), 所在格子位置
#     "area": 0, 所在区域类型 0棋盘内 1下方存储区 2上方存储区 3棋盘外
#     "real": (170.0, 103.91), 实际位置
# },


class GameLogic:
    def __init__(self, cap, first_act, bot_role, player, decision: DecisionUtil):
        self.cap = cap
        self.first_act = first_act
        self.bot_role = bot_role
        self.player = player
        self.decision = decision
        self.user_acting = False

    def user_acting_done(self):
        self.user_acting = False

    def get_decision(self) -> DecisionUtil:
        return self.decision

    def get_cap(self) -> cv2.VideoCapture:
        return self.cap

    def test(self, target_color, target_posi):
        point_detail, area_rects = get_main_status(self.cap)
        self.decision.place_piece(
            target_posi, point_detail, area_rects, overwrite_res=target_color
        )

    def game(self, game_status_update_callback, reset_board_only=False):
        point_detail, area_rects, perv_board = None, None, None
        is_retry = False
        win_rate = None

        GAME_STATUS = GameStatus.INIT

        while loopok():
            if not reset_board_only:
                game_status_update_callback(GAME_STATUS)

            if GAME_STATUS == GameStatus.INIT:
                logger.info("GAME Init")
                point_detail, area_rects = get_main_status(self.cap)
                self.decision.anticheat(
                    GAME_STATUS, point_detail, area_rects, self.bot_role
                )
                GAME_STATUS = self.first_act

                if reset_board_only:
                    return

            elif GAME_STATUS == GameStatus.USER_ACT:
                self.user_acting = True
                logger.info("waiting for user action")
                while self.user_acting and loopok():
                    time.sleep(0.2)

                GAME_STATUS = GameStatus.BOT_ACT

            elif GAME_STATUS == GameStatus.BOT_ACT:
                logger.info("BOT ACT")
                if not is_retry:
                    perv_board = point_detail  # TODO
                point_detail, area_rects = get_main_status(self.cap)

                if self.decision.is_act_illegal(
                    get_board_from_pieces(perv_board),
                    get_board_from_pieces(point_detail),
                ):

                    GAME_STATUS = GameStatus.ANTI_CHEAT
                    logger.info("illegal act, anti-cheat")
                    logger.info(
                        f"perv_board: {get_board_from_pieces(perv_board)}, point_detail: {get_board_from_pieces(point_detail)}"
                    )
                else:
                    is_retry = False
                    logger.info("winner check")
                    winner = check_winner(get_board_from_pieces(point_detail))
                    if winner == ("O" if self.bot_role == 0 else "X"):
                        GAME_STATUS = GameStatus.GAME_OVER
                        win_rate = 100
                        continue
                    elif winner == "tie":
                        GAME_STATUS = GameStatus.GAME_OVER
                        win_rate = 50
                        continue
                    elif winner == ("O" if self.bot_role == 1 else "X"):
                        GAME_STATUS = GameStatus.GAME_OVER
                        win_rate = 0
                        continue

                    logger.info("inferencing best move")
                    move = self.player.get_action(
                        board=get_board_from_pieces(point_detail)
                    )

                    logger.info(f"Move {move}")
                    self.decision.place_piece(move, point_detail, area_rects)
                    point_detail, area_rects = get_main_status(self.cap)
                    perv_board = point_detail

                    winner = check_winner(get_board_from_pieces(point_detail))
                    if winner == ("O" if self.bot_role == 0 else "X"):
                        GAME_STATUS = GameStatus.GAME_OVER
                        win_rate = 100
                        continue
                    elif winner == "tie":
                        GAME_STATUS = GameStatus.GAME_OVER
                        win_rate = 50
                        continue
                    elif winner == ("O" if self.bot_role == 1 else "X"):
                        GAME_STATUS = GameStatus.GAME_OVER
                        win_rate = 0
                        continue

                    GAME_STATUS = GameStatus.USER_ACT
            elif GAME_STATUS == GameStatus.GAME_OVER:
                if win_rate > 99:
                    logger.info("YOU LOSE")
                elif win_rate < 1:
                    logger.info("YOU WIN")
                elif win_rate == 50:
                    logger.info("NOBODY LOSE")

                break
            elif GAME_STATUS == GameStatus.ANTI_CHEAT:
                self.decision.anticheat(
                    GAME_STATUS, point_detail, area_rects, self.bot_role, perv_board
                )
                GAME_STATUS = GameStatus.USER_ACT
                is_retry = True

            # cv2.waitKey(1)

            # input("wait >>>")

        logger.info("GAME OVER")
        # cv2.waitKey(1)
